﻿// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
using System;
using System.Globalization;

namespace Microsoft.Internal
{
    internal static class Failure
    {
        internal enum Mode
        {
            Throw,
            Return
        }

        private static bool FalseOrThrowCantCast(Mode mode, string format, object source, Type contractType)
        {
            if (mode == Mode.Throw)
            {
                string message =
                    String.Format(
                        CultureInfo.CurrentCulture,
                        format,
                        contractType.FullName,
                        source != null ? source.GetType().FullName : "null");
                throw new ArgumentException(message);
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        internal static bool FalseOrThrowCantCast(Mode mode, object source, Type contractType)
        {
            return FalseOrThrowCantCast(mode, Strings.ContractServicesCantCast, source, contractType);
        }

        internal static bool FalseOrThrowCantCastArgumentTypes(Mode mode,
                                                               Type contractType,
                                                               string methodName,
                                                               string parameterName,
                                                               Type parameterType,
                                                               Type sourceParameterType)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastArgumentTypes,
                        contractType.FullName,
                        methodName,
                        parameterName,
                        parameterType.FullName,
                        sourceParameterType.FullName));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        internal static bool FalseOrThrowCantCastInsufficientArguments(Mode mode,
                                                                       Type contractType,
                                                                       string name,
                                                                       int sourceCount,
                                                                       int targetCount)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastInsufficientArguments,
                        contractType.FullName,
                        name,
                        sourceCount,
                        targetCount));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        internal static bool FalseOrThrowCantCastMarkerInterface(Mode mode, Type contractType)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastMarkerInterface,
                        contractType.FullName));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        internal static bool FalseOrThrowCantCastMissingFields(Mode mode, Type contractType, string[] missingMembers)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastMissingFields,
                        contractType.FullName,
                        string.Join(", ", missingMembers)));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        internal static bool FalseOrThrowCantCastNoConstructor(Mode mode, Type contractType)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractservicesCantCastNoConstructor,
                        contractType.FullName));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        internal static bool FalseOrThrowCantCastNull(Mode mode, Type contractType)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastNull,
                        contractType.FullName));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        internal static bool FalseOrThrowCantCastToAtom(Mode mode, object source, Type contractType)
        {
            return FalseOrThrowCantCast(mode, Strings.ContractServicesCantCastToAtom, source, contractType);
        }

        internal static bool FalseOrThrowCantCastToOpenGenericType(Mode mode, Type contractType)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastToOpenGenericType,
                        contractType.FullName));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return false;
        }

        private static object NullOrThrowCantCast(Mode mode, string format, object source, Type contractType)
        {
            if (mode == Mode.Throw)
            {
                string message =
                    String.Format(
                        CultureInfo.CurrentCulture,
                        format,
                        contractType.FullName,
                        source != null ? source.GetType().FullName : "null");
                throw new ArgumentException(message);
            }
            Assumes.IsTrue(mode == Mode.Return);
            return null;
        }

        internal static object NullOrThrowCantCastNull(Mode mode, Type contractType)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastNull,
                        contractType.FullName));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return null;
        }

        internal static object NullOrThrowCantCastSequenceCollection(Mode mode, object source, Type contractType)
        {
            return NullOrThrowCantCast(mode, Strings.ContractServicesCantCastSequenceCollection, source, contractType);
        }

        internal static object NullOrThrowCantCastSequenceIncompatibleItems(Mode mode, Type contractType, Type itemType)
        {
            if (mode == Mode.Throw)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Strings.ContractServicesCantCastSequenceIncompatibleItems,
                        contractType.FullName,
                        itemType.FullName));
            }
            Assumes.IsTrue(mode == Mode.Return);
            return null;
        }

        internal static object NullOrThrowCantCastSequenceList(Mode mode, object source, Type contractType)
        {
            return NullOrThrowCantCast(mode, Strings.ContractServicesCantCastSequenceList, source, contractType);
        }
    }
}